package com.nf;

import javax.sql.DataSource;
import java.sql.*;

/**
 * 　　* @description: TODO
 * 　　* @param
 * 　　* @return
 * 　　* @throws
 * 　　* @author Administrator
 * 　　* @date $ $
 */
public class MiniQueryRunner extends MiniAbstractQueryRunner {
    public MiniQueryRunner() {
        super();
    }

    public MiniQueryRunner(boolean pmdKnownBroken) {
        super(pmdKnownBroken);
    }

    public MiniQueryRunner(DataSource ds) {
        super(ds);
    }

    public MiniQueryRunner(DataSource ds, boolean pmdKnownBroken) {
        super(ds, pmdKnownBroken);
    }

    public int update(Connection connection, String sql) throws SQLException {
        return this.update(connection, false, sql, (Object[]) null);
    }

    public int update(Connection connection, String sql, Object param) throws SQLException {
        return this.update(connection, false, sql, new Object[]{param});
    }

    public int update(Connection connection, String sql, Object... params) throws SQLException {
        return this.update(connection, false, sql, params);
    }

    public int update(String sql) throws SQLException {
        Connection connection = this.prepareConnection();
        return this.update(connection, true, sql, (Object[]) null);
    }

    public int update(String sql, Object param) throws SQLException {
        Connection connection = this.prepareConnection();
        return this.update(connection, true, sql, new Object[]{param});
    }

    public int update(String sql, Object... params) throws SQLException {
        Connection connection = this.prepareConnection();
        return this.update(connection, true, sql, params);
    }

    private int update(Connection conn, boolean closeConn, String sql, Object... params) throws SQLException {
        if (conn == null) {
            throw new SQLException("Null connection");
        }
        if (sql == null) {
            if (closeConn) {
                close(conn);
            }
            throw new SQLException("Null SQL statement");
        }
        PreparedStatement stmt = null;
        int rows = 0;
        try {
            stmt = this.prepareStatement(conn, sql);
            this.fillStatement(stmt, params);
            rows = stmt.executeUpdate();
        } catch (SQLException e) {
            this.rethrow(e, sql, params);

        } finally {
            close(stmt);
            if (closeConn) {
                close(conn);
            }
        }
        return rows;
    }

    public <T> T query(String sql, MiniResultSetHandler<T> rsh, Object... params) throws SQLException {
        Connection conn = this.prepareConnection();
        return this.<T>query(conn, true, sql, rsh, params);
    }

    public <T> T query(String sql, MiniResultSetHandler<T> rsh) throws SQLException {
        Connection conn = this.prepareConnection();

        return this.<T>query(conn, true, sql, rsh, (Object[]) null);
    }

    private <T> T query(Connection conn, boolean closeConn, String sql, MiniResultSetHandler<T> rsh, Object... params) throws SQLException {
        if (conn == null) {
            throw new SQLException("Null connection");
        }

        if (sql == null) {
            if (closeConn) {
                close(conn);
            }
            throw new SQLException("Null SQL statement");
        }

        if (rsh == null) {
            if (closeConn) {
                close(conn);
            }
            throw new SQLException("Null ResultSetHandler");
        }

        PreparedStatement stmt = null;
        ResultSet rs = null;
        T result = null;

        try {
            stmt = this.prepareStatement(conn, sql);
            this.fillStatement(stmt, params);
            //rs = this.wrap(stmt.executeQuery());
            rs = stmt.executeQuery();
            result = rsh.handle(rs);
        } catch (SQLException e) {
            this.rethrow(e, sql, params);

        } finally {
            try {
                close(rs);
            } finally {
                close(stmt);
                if (closeConn) {
                    close(conn);
                }
            }
        }

        return result;
    }


    public <T> T insert(String sql, MiniResultSetHandler<T> rsh) throws SQLException {
        return insert(this.prepareConnection(), true, sql, rsh, (Object[]) null);
    }

    public <T> T insert(String sql, MiniResultSetHandler<T> rsh, Object... params) throws SQLException {
        return insert(this.prepareConnection(), true, sql, rsh, params);
    }

    public <T> T insert(Connection conn, String sql, MiniResultSetHandler<T> rsh) throws SQLException {
        return insert(conn, false, sql, rsh, (Object[]) null);
    }

    public <T> T insert(Connection conn, String sql, MiniResultSetHandler<T> rsh, Object... params) throws SQLException {
        return insert(conn, false, sql, rsh, params);
    }
    private <T> T insert(Connection conn, boolean closeConn, String sql, MiniResultSetHandler<T> rsh, Object... params)
            throws SQLException {
        if (conn == null) {
            throw new SQLException("Null connection");
        }

        if (sql == null) {
            if (closeConn) {
                close(conn);
            }
            throw new SQLException("Null SQL statement");
        }

        if (rsh == null) {
            if (closeConn) {
                close(conn);
            }
            throw new SQLException("Null ResultSetHandler");
        }

        PreparedStatement stmt = null;
        T generatedKeys = null;

        try {
            stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            this.fillStatement(stmt, params);
            stmt.executeUpdate();
            ResultSet resultSet = stmt.getGeneratedKeys();
            generatedKeys = rsh.handle(resultSet);
        } catch (SQLException e) {
            this.rethrow(e, sql, params);
        } finally {
            close(stmt);
            if (closeConn) {
                close(conn);
            }
        }

        return generatedKeys;
    }
}
